perm filename OTLSER.MID[NET,MRC]2 blob
sn#339539 filedate 1978-03-05 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00011 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 TITLE OTLSER
C00004 00003 Data area
C00006 00004 Interrupt server
C00008 00005 Start of program
C00010 00006 Log this connection
C00012 00007 Initialize the connection
C00014 00008 Network input interrupt
C00016 00009 PTY input interrupt
C00017 00010 Network command server
C00019 00011 Subroutines
C00021 ENDMK
C⊗;
TITLE OTLSER
SUBTTL Definitions
; Mark Crispin, SU-AI, March 1978
; Assembly switches
IFNDEF SVRSKT,SVRSKT==1 ; default listen socket
IFNDEF LOKTMO,LOKTMO==5 ; # of 15-second frobs of lock timeout
IFNDEF PDLLEN,PDLLEN==50 ; stack length
; AC definitions. 0→3 are used by NETWRK
X=4 ? A=5 ? B=6 ? P=17
; Macro to send a TELNET command
DEFINE TELCMD CMDLST
OUTSTR [ASCIZ/⊗!CMDLST!*
/]
IRPS CMD,,CMDLST
MOVEI CMD
PUSHJ P,NETOCH
TERMIN
PUSHJ P,NETSND
TERMIN
; SAIL system bit definitions
INTPTO==001000,, ; PTY interrupt
INTCLK==000200,, ; clock interrupt
ECHARR==010000,, ; echo controls with uparrow
IMPBIT==001000,, ; IMP TTY
FCS== 000020,, ; full character set mode
TBXPND==000010,, ; expand tabs to spaces
FULTWX==000004,, ; no echo
TLKRNG==000001,, ; TALKing
SUBTTL Data area
; TTYSET command words
ECHON: 002400,,(FULTWX) ; echo on
ECHOFF: 001400,,(FULTWX) ; echo off
GAGOFF: 024400,,0 ; gag off
; Terminal location string
TERMID: 'TERMID
CORBEG==. ; start of initialized core storage
TERSTR: BLOCK 10. ; console location string
; Interrupt flags
PTINTP: BLOCK 1 ; -1 → PTI interrupt
NTINTP: BLOCK 1 ; -1 → NTI interrupt
NTOINP: BLOCK 1 ; -1 → INS interrupt
; Protocol flags
ECHOP: BLOCK 1 ; -1 → remote echoing
; Other flags
NODETP: BLOCK 1 ; -1 → don't detach this guy
NEWLNP: BLOCK 1 ; -1 → starting newline
LFFLSP: BLOCK 1 ; -1 → PTISER's LF flush kludge
; Other storage
TTYLIN: BLOCK 1 ; line number of PTY
IDLTIM: BLOCK 1 ; idle time in 15-second units
WHOBUF: BLOCK 22 ; wholine buffer
PDL: BLOCK PDLLEN ; stack
COREND==.-1 ; end of initialized storage
SUBTTL Interrupt server
; Interrupts only set flags which the main program (normally in INTW⊗
; state) looks at.
INTSER: SKIPN X,JOBCNI ; get interrupt status
JRST 4,.-1
TLNE X,(INTPTO) ; PTY int
SETOM PTINTP
TLNE X,(INTCLK) ; CLK int
JRST CLKSER
TLNE X,(INTINP) ; NTI int
SETOM NTINTP
TLNE X,(INTIMS) ; status change
JRST INTDIE
TLNE X,(INTINR)
OUTSTR [ASCIZ/*INR*
/]
TLNN X,(INTINS) ; IMP INS int
DISMIS
SOS NTOINP
OUTSTR [ASCIZ/*INS*
/]
DISMIS
; Service clock interrupt
CLKSER: AOSE IDLTIM ; bump idle time
JRST CLKSR1
UNLOCK ; idle timeout; unlock
MOVE TTYLIN
PTGETL
TLNE 1,(TLKRNG) ; TALKing?
JRST CLKSR1 ; don't kill him if so!
TTYJOB
JUMPE INTDIE ; idle and not logged in--bye bye!
CLKSR1: MOVEI 2 ; check connection status
MTAPE NET,
TLNN 1,(CLSS\CLSR) ; send side gronked?
TLNE 2,(CLSS\CLSR) ; receive side?
JRST INTDIE
DISMIS
SUBTTL Start of program
OTLSER: JFCL
RESET
MOVE ['OTLSER]
SETNAM
SETZM CORBEG
MOVE [CORBEG,,CORBEG+1]
BLT COREND
MOVE P,[PDL(-PDLLEN)]
MOVEI [DEBREAK ? EXIT]
MOVEM JOBAPR
CLKINT 5.*60.*60. ; must die if around too long
OUTSTR [ASCIZ/OTLSER started
/]
; Listen for a connection on our socket
SETOM NODETP ; don't try to detach
MOVEI SVRSKT
MOVEM LSNSKT
PUSHJ P,LISTEN
; Set up interrupts
MOVEI INTSER
MOVEM JOBAPR ; set up server location
CLKINT 60.*15. ; start slow ticking clock
MOVSI (INTPTO\INTCLK\INTINR\INTINS\INTIMS\INTINP)
INTENB ; turn on interrupts
; Set up terminal id for interested spies
MOVEI TERMID
MOVEM JOBVER
SUBTTL Log this connection
OUTSTR [ASCIZ/Connected to /]
PUSHJ P,MAPHST ; map in host table
MOVE HOST
PUSHJ P,HSTNUM ; get HDB
JFCL ; sorry about errors
MOVEI A,(1) ; host name
HRLI A,440700
SKIPA X,[440700,,TERSTR]
CPYHST: IDPB B,X
ILDB B,A
JUMPN B,CPYHST
HLRZ A,1 ; pointer to system name
MOVE B,(A) ; get system name
MOVE A,FSOCKT ; and ICP socket
CAMN B,[ASCII/TIP/] ; on a TIP?
TRNE A,177774 ; just paranoia; make sure a TIP port
JRST NOTTIP
MOVEI B,"#
IDPB B,X
LSH A,-16.
IDIVI A,8. ; ports are octal
JUMPE A,1DIGTP
ADDI A,"0 ? IDPB A,X
1DIGTP: ADDI B,"0 ? IDPB B,X
NOTTIP: PUSHJ P,SETANM ; set our alias name
PUSHJ P,UNMHST ; map out the host table
OUTSTR TERSTR
OUTSTR [ASCIZ/
/]
SUBTTL Initialize the connection
; Send initial protocol commands
TELCMD [NEC]
SETOM ECHOP
; Greet the user
MOVEI X,[ASCIZ/SU A.I. Lab KL-10
/]
PUSHJ P,SNDMSG
; Get a PTY, keep its number in A
PTYGET A
JRST [ MOVEI X,[ASCIZ/All network ports in use.
/]
PUSHJ P,SNDMSG
PUSHJ P,CLOSER
JRST SUICID]
HRRZM A,TTYLIN ; dumb interrupts
MOVSI (A)
IRPS FOO,,ECHON ECHOFF GAGOFF
IORM FOO
TERMIN
MOVSI B,(ECHARR\IMPBIT\FCS\TBXPND)
PTSETL A ; set initial bits
HRROI GAGOFF
TTYSET ; turn GAG bit off
MOVEI B,↑M
PTWR1W A
; Final initialization
MOVNI 1,LOKTMO
MOVEM 1,IDLTIM ; initialize lock timeout
LOCK ; keep response good
SETZM NODETP ; okay to detach jobs now
JRST NTISER ; check network input
; Main program loop
MAINL: IWAIT ; wait for an interrupt
MAINL0: AOSG NTINTP ; net input?
JRST NTISER
AOSG PTINTP ; PTY input?
JRST PTISER
JRST MAINL ; back to sleep for us
SUBTTL Network input interrupt
NTISER: PUSHJ P,NETICH ; get character from the network
JRST MAINL0 ; network input buffer empty
SKIPL IDLTIM
LOCK
MOVNI 1,LOKTMO
MOVEM 1,IDLTIM ; reset idle time
CAIL 200 ; network command?
JRST NCMSER
AOSE NEWLNP ; flush second half of NL?
JRST NTISR2
JUMPE NTISER ; yah, flush nulls or
CAIN ↑J ; LFs
JRST NTISER
NTISR2: CAIE ↑M ; CR?
JRST NTISR1
SKIPN ECHOP ; if in local mode
SETOM LFFLSP ; kludge to prevent system echo of LF's
SETOM NEWLNP ; maybe flush an LF
NTISR1: SKIPGE NTOINP ; still in flushify mode?
JRST NTISER ; too bad
MOVE B,
PTWR1S A ; send character to PTY
JRST [ MOVEI ↑G ; bell
PUSHJ 17,NETOCH
PUSHJ 17,NETSND ; output it
JRST NTISER]
JRST NTISER ; try for more user characters
SUBTTL PTY input interrupt
PTISER: PTRD1S A ; get a character from the PTY
JRST MAINL0 ; PTY input buffer empty
SKIPL IDLTIM
LOCK
PTISR1: MOVNI 1,LOKTMO
MOVEM 1,IDLTIM ; reset idle time
MOVE B
ANDI 377 ; flush funny 400 bit
CAIN ↑J ; LF? (someday remove this kludge)
AOSE LFFLSP ; yes, second part of NL?
PUSHJ P,NETOCH ; send character to net
PTRD1S A ; try for more while here
CAIA
JRST PTISR1 ; more coming
PUSHJ P,NETSND ; force buffer out
JRST MAINL0 ; scan the world again
SUBTTL Network command server
DEFINE TPC CODE
CODE
IRPS NAME,,CODE
CAIN NAME
JRST [OUTSTR [ASCIZ/!NAME!/] ? JRST NAME!SER]
.ISTOP
TERMIN
TERMIN
NCMSER: OUTCHR ["*]
TPC DMK==200 ; data mark
TPC BRK==201 ; break
TPC NOP==202 ; no-op
TPC NEC==203 ; no echo
TPC ECH==204 ; echo
TPC HID==205 ; hide input
TPC ASC==240 ; ASCII mode
TPC TRA==241 ; transparent
TPC IBM==242 ; EBCDIC mode
TPC YRC==243 ; your code
TPC MYC==244 ; my code
OUTSTR [ASCIZ/???/]
; Here when we return from a command (or for commands we no-op)
NOPSER: HIDSER: ASCSER: TRASER: IBMSER: YRCSER: MYCSER:
CMDONE: OUTSTR [ASCIZ/*
/]
JRST NTISER
DMKSER: AOS NTOINP ; data mark
JRST CMDONE
BRKSER: MOVEI B,[.BYTE 9 ? 600 ? 600 ? 0]; CALL
PTWRS9 A
JRST CMDONE
NECSER: SETZM ECHOP
HRROI ECHOFF
TTYSET
JRST CMDONE
ECHSER: SETOM ECHOP
HRROI ECHON
TTYSET
JRST CMDONE
SUBTTL Subroutines
; Send a message, b.p. in X
SNDMSG: TLOA X,440700 ; set up b.p.
MSGLUP: PUSHJ P,NETOCH
ILDB X
JUMPN MSGLUP ; continue until a null hit
JRST NETSND
; Here to suicide on network errors or idle timeout
INTDIE: INTMSK [0] ; no more interrupts
DEBREAK ; out of interrupt level
SUICID: OUTSTR [ASCIZ/Connection closed.
/]
SKIPE NODETP
JRST DIEDIE ; logout the guy
MOVE A,TTYLIN
TTYJOB A,
JUMPE A,DIEDIE
MOVE A,TTYLIN
MOVEI B,7
PTJOBX A ; clear PTY's input buffer
PTRD1S A ; slurp up stuff in buffer
CAIA
JRST .-2
MOVEI B,[.BYTE 9 ? 600 ? 600 ? "D ? "E ? "T ? "A ? "C ? "H ? ↑M ? ↑J ? 0]
PTWRS9 A
MOVEI 5.
SLEEP ; give it time to happen
PTRD1S A ; slurp up what's left in the buffer
JRST DIEDIE
JRST .-2
DIEDIE: RESET ? EXIT
...LIT: CONSTANTS
; Wonderful network routines
SVRRTS==-1 ; include server routines
ERRTNS==-1 ; include error routines
ERRHAN==-1 ; include automagic error handling
ERRINS==<JRST SUICID> ; error instruction
HSTTAB==-1 ; include host table magic
HSTSIX==-1 ; and alias name kludge
.INSRT NETWRK[NET,MRC]
END OTLSER